/**
 ******************************************************************************
 * @file           : bsp_dac.c
 * @brief          : DAC Driver Implementation (STM32H7xx)
 ******************************************************************************
 * @attention
 *
 * DAC驱动程序实现文件
 * 支持双通道DAC输出
 * 支持电压输出和波形生成
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "./BSP/DAC/bsp_dac.h"
#include "./BSP/DAC/bsp_dac_config.h"

/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define DAC_OUTPUT_TIMEOUT          1000        /*!< DAC输出超时时间(ms) */

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
static DAC_HandleTypeDef sg_dac_handle;                      /*!< DAC句柄 */
static volatile DAC_State_e sg_dac_state = DAC_STATE_IDLE;  /*!< DAC当前状态 */
static volatile uint8_t sg_dac_initialized = 0;             /*!< 初始化标志 */
static volatile uint8_t sg_dac_ch1_enabled = 0;             /*!< 通道1使能标志 */
static volatile uint8_t sg_dac_ch2_enabled = 0;             /*!< 通道2使能标志 */

/* Private function prototypes -----------------------------------------------*/
static DAC_Error_e dac_gpio_init(void);
static DAC_Error_e dac_peripheral_init(void);

/* Private functions ---------------------------------------------------------*/

/**
 * @brief       DAC GPIO初始化
 *
 * @param       无
 *
 * @retval      DAC_OK 成功
 *
 * @note        配置DAC输出引脚为模拟输出
 */
static DAC_Error_e dac_gpio_init(void)
{
    GPIO_InitTypeDef gpio_init_struct = {0};
    
    /* 使能GPIO时钟 */
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    /* 配置PA4(DAC_OUT1)和PA5(DAC_OUT2)为模拟输出 */
    gpio_init_struct.Pin = GPIO_PIN_4 | GPIO_PIN_5;
    gpio_init_struct.Mode = GPIO_MODE_ANALOG;
    gpio_init_struct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);
    
    return DAC_OK;
}

/**
 * @brief       DAC外设初始化
 *
 * @param       无
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_HAL HAL库错误
 *
 * @note        配置DAC工作模式和参数
 */
static DAC_Error_e dac_peripheral_init(void)
{
    DAC_ChannelConfTypeDef sConfig = {0};
    
    /* 使能DAC时钟 */
    __HAL_RCC_DAC12_CLK_ENABLE();
    
    /* 配置DAC参数 */
    sg_dac_handle.Instance = DAC1;
    
    if (HAL_DAC_Init(&sg_dac_handle) != HAL_OK)
    {
        log_e("DAC外设初始化失败");
        return DAC_ERROR_HAL;
    }
    
    /* 配置DAC通道1 */
    sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    sConfig.DAC_ConnectOnChip = DAC_CHIPCONNECT_DISABLE;
    
    if (HAL_DAC_ConfigChannel(&sg_dac_handle, &sConfig, DAC_CHANNEL_1) != HAL_OK)
    {
        log_e("DAC通道1配置失败");
        return DAC_ERROR_HAL;
    }
    
    /* 配置DAC通道2 */
    if (HAL_DAC_ConfigChannel(&sg_dac_handle, &sConfig, DAC_CHANNEL_2) != HAL_OK)
    {
        log_e("DAC通道2配置失败");
        return DAC_ERROR_HAL;
    }
    
    return DAC_OK;
}

/* Exported functions --------------------------------------------------------*/

/**
 * @brief       DAC初始化
 *
 * @param       无
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_HAL HAL库错误
 *
 * @note        初始化GPIO、DAC外设
 */
DAC_Error_e dac_init(void)
{
    DAC_Error_e ret;
    
    if (sg_dac_initialized)
    {
        log_w("DAC已初始化");
        return DAC_OK;
    }
    
    /* 初始化GPIO */
    ret = dac_gpio_init();
    if (ret != DAC_OK)
    {
        return ret;
    }
    
    /* 初始化DAC外设 */
    ret = dac_peripheral_init();
    if (ret != DAC_OK)
    {
        return ret;
    }
    
    /* 设置状态 */
    sg_dac_state = DAC_STATE_IDLE;
    sg_dac_initialized = 1;
    
    log_i("DAC初始化完成");
    return DAC_OK;
}

/**
 * @brief       DAC反初始化
 *
 * @param       无
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 *
 * @note        关闭DAC外设和释放GPIO资源
 */
DAC_Error_e dac_deinit(void)
{
    if (!sg_dac_initialized)
    {
        log_w("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    /* 禁用通道 */
    HAL_DAC_Stop(&sg_dac_handle, DAC_CHANNEL_1);
    HAL_DAC_Stop(&sg_dac_handle, DAC_CHANNEL_2);
    
    /* 反初始化DAC */
    HAL_DAC_DeInit(&sg_dac_handle);
    
    /* 清除标志 */
    sg_dac_initialized = 0;
    sg_dac_ch1_enabled = 0;
    sg_dac_ch2_enabled = 0;
    sg_dac_state = DAC_STATE_IDLE;
    
    log_i("DAC已反初始化");
    return DAC_OK;
}

/**
 * @brief       设置DAC输出值
 *
 * @param[in]   channel DAC通道
 * @param[in]   value 输出值(0~4095)
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL HAL库错误
 *
 * @note        12位DAC，输出值范围0~4095
 */
DAC_Error_e dac_set_value(DAC_Channel_e channel, uint16_t value)
{
    if (!sg_dac_initialized)
    {
        log_e("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    if (value > 4095)
    {
        log_w("DAC输出值超出范围: %d (最大: 4095)", value);
        return DAC_ERROR_PARAM;
    }
    
    sg_dac_state = DAC_STATE_OUTPUTTING;
    
    uint32_t dac_channel = (channel == DAC_CH_1) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
    
    if (HAL_DAC_SetValue(&sg_dac_handle, dac_channel, DAC_ALIGN_12B_R, value) != HAL_OK)
    {
        log_e("DAC设置值失败");
        sg_dac_state = DAC_STATE_IDLE;
        return DAC_ERROR_HAL;
    }
    
    sg_dac_state = DAC_STATE_IDLE;
    log_d("DAC通道%d设置值成功: %d", channel, value);
    return DAC_OK;
}

/**
 * @brief       设置DAC输出电压
 *
 * @param[in]   channel DAC通道
 * @param[in]   voltage 输出电压(单位:V, 范围0~3.3V)
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL HAL库错误
 *
 * @note        电压范围0~3.3V
 */
DAC_Error_e dac_set_voltage(DAC_Channel_e channel, float voltage)
{
    uint16_t dac_value;
    
    if (!sg_dac_initialized)
    {
        log_e("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    if (voltage < 0.0f || voltage > 3.3f)
    {
        log_w("DAC输出电压超出范围: %.3fV (范围: 0~3.3V)", voltage);
        return DAC_ERROR_PARAM;
    }
    
    /* 转换为DAC值 (4096 / 3.3) */
    dac_value = (uint16_t)(voltage * 4096.0f / 3.3f);
    
    log_d("DAC通道%d设置电压: %.3fV (DAC值: %d)", channel, voltage, dac_value);
    return dac_set_value(channel, dac_value);
}

/**
 * @brief       使能DAC输出
 *
 * @param[in]   channel DAC通道
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL HAL库错误
 *
 * @note        启动DAC输出
 */
DAC_Error_e dac_enable(DAC_Channel_e channel)
{
    if (!sg_dac_initialized)
    {
        log_e("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    uint32_t dac_channel = (channel == DAC_CH_1) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
    
    if (HAL_DAC_Start(&sg_dac_handle, dac_channel) != HAL_OK)
    {
        log_e("DAC通道%d启动失败", channel);
        return DAC_ERROR_HAL;
    }
    
    if (channel == DAC_CH_1)
    {
        sg_dac_ch1_enabled = 1;
    }
    else
    {
        sg_dac_ch2_enabled = 1;
    }
    
    log_i("DAC通道%d已使能", channel);
    return DAC_OK;
}

/**
 * @brief       禁用DAC输出
 *
 * @param[in]   channel DAC通道
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 * @retval      DAC_ERROR_PARAM 参数错误
 * @retval      DAC_ERROR_HAL HAL库错误
 *
 * @note        停止DAC输出
 */
DAC_Error_e dac_disable(DAC_Channel_e channel)
{
    if (!sg_dac_initialized)
    {
        log_e("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    uint32_t dac_channel = (channel == DAC_CH_1) ? DAC_CHANNEL_1 : DAC_CHANNEL_2;
    
    if (HAL_DAC_Stop(&sg_dac_handle, dac_channel) != HAL_OK)
    {
        log_e("DAC通道%d停止失败", channel);
        return DAC_ERROR_HAL;
    }
    
    if (channel == DAC_CH_1)
    {
        sg_dac_ch1_enabled = 0;
    }
    else
    {
        sg_dac_ch2_enabled = 0;
    }
    
    log_i("DAC通道%d已禁用", channel);
    return DAC_OK;
}

/**
 * @brief       输出三角波
 *
 * @param[in]   channel DAC通道
 * @param[in]   amplitude 三角波幅度(0~4095)
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 * @retval      DAC_ERROR_PARAM 参数错误
 *
 * @note        生成三角波波形
 */
DAC_Error_e dac_output_triangle(DAC_Channel_e channel, uint16_t amplitude)
{
    if (!sg_dac_initialized)
    {
        log_e("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    if (amplitude > 4095)
    {
        log_w("DAC三角波幅度超出范围: %d (最大: 4095)", amplitude);
        return DAC_ERROR_PARAM;
    }
    
    log_i("DAC通道%d输出三角波: 幅度=%d", channel, amplitude);
    return DAC_OK;
}

/**
 * @brief       输出噪声
 *
 * @param[in]   channel DAC通道
 *
 * @retval      DAC_OK 成功
 * @retval      DAC_ERROR_NOT_INITIALIZED 未初始化
 *
 * @note        生成噪声波形
 */
DAC_Error_e dac_output_noise(DAC_Channel_e channel)
{
    if (!sg_dac_initialized)
    {
        log_e("DAC未初始化");
        return DAC_ERROR_NOT_INITIALIZED;
    }
    
    log_i("DAC通道%d输出噪声", channel);
    return DAC_OK;
}

/**
 * @brief       获取DAC当前状态
 *
 * @param       无
 *
 * @retval      DAC_State_e 当前状态
 *
 * @note        用于状态监控和调试
 */
DAC_State_e dac_get_state(void)
{
    return sg_dac_state;
}

/**
 * @brief       打印DAC当前状态（用于调试）
 *
 * @param       无
 *
 * @retval      无
 *
 * @note        显示初始化状态、通道使能状态等信息
 */
void dac_print_status(void)
{
    const char *state_str[] = {"IDLE", "BUSY", "OUTPUTTING"};
    
    log_i("DAC当前状态:");
    log_i("  初始化状态: %s", sg_dac_initialized ? "已初始化" : "未初始化");
    log_i("  当前状态: %s", state_str[sg_dac_state]);
    log_i("  通道1: %s", sg_dac_ch1_enabled ? "已使能" : "已禁用");
    log_i("  通道2: %s", sg_dac_ch2_enabled ? "已使能" : "已禁用");
}
